package com.jingdianjichi.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.jingdianjichi.auth.common.connstants.AuthConstant;
import com.jingdianjichi.auth.common.enums.AuthUserStatusEnum;
import com.jingdianjichi.auth.common.enums.IsDeletedFlagEnum;
import com.jingdianjichi.auth.domain.convert.AuthUserBOConverter;
import com.jingdianjichi.auth.domain.entity.AuthUserBO;
import com.jingdianjichi.auth.domain.redis.RedisUtil;
import com.jingdianjichi.auth.domain.service.AuthUserDomainService;
import com.jingdianjichi.auth.infra.basic.entity.*;
import com.jingdianjichi.auth.infra.basic.service.AuthRolePermissionService;
import com.jingdianjichi.auth.infra.basic.service.AuthRoleService;
import com.jingdianjichi.auth.infra.basic.service.AuthUserRoleService;
import com.jingdianjichi.auth.infra.basic.service.AuthUserService;
import com.jingdianjichi.auth.infra.basic.service.impl.AuthPermissionServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author 86156
 * @version 1.0
 * @date 2024-10-31 9:55
 */
@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {

    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private AuthPermissionServiceImpl authPermissionService;

    private String salt = "chicken";

    private String authPermissionPrefix = "auth.permission";

    private String authRolePrefix = "auth.role";

    private static final String LOGIN_PREFIX = "loginCode";

    /**
     * 用户注册
     * @param authUserBO 实体类
     * @return 是否成功
     */
    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean registry(AuthUserBO authUserBO) {
        if(log.isInfoEnabled()){
            log.info("AuthUserDomainServiceImpl.registry.bo: {}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        // 校验用户是否已经注册,判重
        Integer exist = authUserService.queryByConditionCount(authUser);
        if(exist > 0){
            return true;
        }

        // 数据库密码加盐
        if(StringUtils.isNotBlank(authUser.getPassword())){
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(),salt));
        }
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        Integer count = authUserService.insert(authUser);

        // 用户和角色做一个关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        List<AuthRole> rolelist = authRoleService.queryByCondition(authRole);
        Long roleId = rolelist.get(0).getId();
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(authUser.getId());
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);

        // 与redis缓存交互
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        redisUtil.set(roleKey,new Gson().toJson(roleList));

        // 从角色权限关联表中根据roleId查出所有的permissionId
        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> authRolePermissions = authRolePermissionService.queryByCondition(authRolePermission);
        List<Long> permissionList = authRolePermissions.stream().map(AuthRolePermission::getPermissionId).collect(Collectors.toList());

        // 根据权限id集合查询权限详情集合
        List<AuthPermission> authPermissionList =  authPermissionService.queryByIds(permissionList);
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        redisUtil.set(permissionKey,new Gson().toJson(authPermissionList));


        return count>0;
    }

    /**
     * 更新用户信息
     */
    @Override
    public Boolean update(AuthUserBO authUserBO) {
        if(log.isInfoEnabled()){
            log.info("AuthUserDomainServiceImpl.update.bo: {}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = AuthUserBOConverter.instance.authUserBoToEntity(authUserBO);
        int count = authUserService.update(authUser);
        return count>0;
    }

    /**
     * 删除用户信息
     */
    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        if(log.isInfoEnabled()){
            log.info("AuthUserDomainServiceImpl.delete.authUserBO: {}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        return authUserService.update(authUser)>0;
    }

    /**
     * 启用/禁用
     */
    @Override
    public Boolean changeStatus(AuthUserBO authUserBO) {
        if(log.isInfoEnabled()){
            log.info("AuthUserDomainServiceImpl.delete.authUserBO: {}", JSON.toJSONString(authUserBO));
        }
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setStatus(authUserBO.getStatus());
        return authUserService.update(authUser)>0;
    }

    @Override
    public SaTokenInfo doLogin(String validCode) {
        if(log.isInfoEnabled()){
            log.info("AuthUserDomainServiceImpl.doLogin.validCode: {}", validCode);
        }
        String loginKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if(StringUtils.isBlank(openId)){
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        this.registry(authUserBO);
        StpUtil.login(openId);
        return StpUtil.getTokenInfo();
    }

    /**
     * 获取用户详情
     */
    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        if(log.isInfoEnabled()){
            log.info("AuthUserDomainServiceImpl.getUserInfo.authUserBO: {}", authUserBO);
        }
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> authUsers = authUserService.queryAllByLimit(authUser);
        if(CollectionUtils.isEmpty(authUsers)){
            return new AuthUserBO();
        }
        AuthUser existUser = authUsers.get(0);
        return AuthUserBOConverter.instance.authUserEntityToBo(existUser);
    }


}
